In this document, we analyse missing data patterns in the dataset.

First of all, we noticed that there are some issues with the dataset and therefore, for now, we restrict the dataset to observations not subject to these issues. In particular, we do not have any pollution data for 2014 nor for NO in 2015 and very few observations for PMs in 2019. These issue do not come from actual missing data but are due to issue with the package we used to access the pollution data. These data are available through the EEA interface.

data <- data_imputation %>%  
  mutate(
    year = as.factor(year(date)),
    month = as.factor(month(date)),
    day_of_month = as.factor(day(date)),
    day_in_week = as.factor(wday(date)),
    hour = as.factor(hour(date)),
    missing = is.na(concentration)
  ) %>% 
  filter(year != 2014) %>% 
  filter(!(year == 2015 & pollutant == "no")) %>% 
  filter(!(year == 2019 & str_sub(pollutant, 1, 2) == "pm")) 
  
  
rm(data_imputation)

Share of missing data in covariates

Error: Can't combine `year` <factor<ea356>> and `city` <double>.

In order to understand these previous results, we break down the analysis by year and represent the results in a graph, for readability.

In complete case analyses, observations for which any variable is missing are dropped. One may therefore wonder what is the share of dropped observations in a complete case analysis. We only consider variables which are potentially relevant. We also drop the UV radiation variable due to its large share of missingness.

Carrying out a complete case analysis would lead to drop 54.9679616% of the observations. Only considering missing covariates (and not missingness in concentration data) would lead to drop 50.3371618% of the observations.

Location of measurement stations

The stations considered are located in the 17 biggest largest in France:

Missing data patterns in air pollution data

Here, we investigate whether missing pollutant concentration data varies across different dimentions.

The overall share of missing values is 0.046308.

Balance grahs

we first investigate whether covariates are ballanced between observations for which concentration data is missing and non missing.

It seems that most weather covariates are balanced between the two groups. Average temperature and UV radiation may however be slightly different between the two groups.

We can refine this analysis by looking separately across cities.

Evolution of the share of missing values with the values of covariates

In this section, we investigate whether the share of missing values varies with the values of covariates. One may expect that, for extreme values of some covariates, such as temperature, wind speed or precipitation level for example, measurement instruments are more likely to be defective, leading to more missing values.

Across pollutants

One can notice that the share of missing values varies across pollutants, up to about a factor two. This higlights the potential necessity of analysing missingness patterns independently across pollutants.

Across dates and time

We then investigate whether the share of missing values evolves with dates and time.

[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

Overall, we notice that, along the time dimension data almost seems to be missing at random appart from a decreasing trend in the proportion of missing data

We also explore more closely these patterns for some variables by decomposing them by year, month or pollutant.

Only consider first missing value

If data is missing due to external factors, what matters might be the value of these external factor when the data started missing, ie potentially when the sensor first became defective. As a consequence, we plot the same graphs as before but only considering hours were the data started missing, not considering later and consecutive missing observations.

As compared to the full sample, the share of missing data decreases since we discarded many observations with missing values (every observation which was not the first observation of their period of missing data). Hence, the share of missing data is not informative in itself, only potential differences in this share across “grouping variables”.

Error in group_by(site, pollutant) : object 'site' not found

Simultaneous missingness

In this section, we analyse whether some patterns of simultaneous missingness appear in the data. We wonder whether, for a given station, data is simultaneously missing for several pollutants or whether, for a given city, data is simultaneously missing for several stations.

Across pollutants

We investigate whether, in a given station, when one pollutant is missing, other pollutants are also missing. Such a missingness pattern could arise if sensors for different pollutants function jointly.

We count the number of pollutants which are simultaneously missing for every station*date couple. Note that this analysis does not consider that an observation is missing when a given station is closed for a pollutant.

Number of pollutants with concentration data missing Number of dates Proportion
0 3682071 0.8996952
1 300244 0.0733631
2 83885 0.0204969
3 17271 0.0042201
4 6288 0.0015364
5 2139 0.0005227
6 678 0.0001657

We could also investigate whether this pattern varies with various weather variables.

Now, part of the stations do not measure values for all pollutants. Thus, it is interesting to compute the proportion of pollutants measured by station for which data is missing.

Share of pollutants for which concentration data is missing Number of dates Proportion Proportion among dates with missing observations
0.0000000 3682071 0.8996952 NA
0.1666667 26765 0.0065399 0.0652002
0.2000000 44184 0.0107961 0.1076333
0.2500000 71990 0.0175904 0.1753694
0.3333333 63008 0.0153957 0.1534890
0.4000000 8892 0.0021727 0.0216611
0.5000000 72044 0.0176036 0.1755009
0.6000000 1989 0.0004860 0.0048453
0.6666667 14931 0.0036483 0.0363723
0.7500000 1659 0.0004054 0.0040414
0.8000000 823 0.0002011 0.0020048
0.8333333 148 0.0000362 0.0003605
1.0000000 104072 0.0254295 0.2535219

Since for analyses studying the link btween air pollution and health have a particular focus on background station, we carry out the same analysis for these stations.

Across stations in a city

Ultimately, analyses studying health effects of air pollution often only use one measure of concentration per city and per date. In most cases, there are several air pollution measurement stations per city. To get a unique measure of air pollution for a given city, the common practice consists in averaging pollutants concentrations from all background stations in this city. We may wonder to what extent concentration data is simultaneously missing in several stations of a given city. We therefore compute the average proportion of stations per city in which data missing.

Share of stations in a city for which concentration data is missing Number of dates Proportion Proportion among dates with missing observations
0.0000000 4186511 0.9334591 NA
0.1666667 17198 0.0038346 0.0576279
0.2000000 3998 0.0008914 0.0133967
0.2500000 1929 0.0004301 0.0064638
0.3333333 48112 0.0107274 0.1612160
0.4000000 90 0.0000201 0.0003016
0.5000000 86908 0.0193777 0.2912154
0.6000000 2 0.0000004 0.0000067
0.6666667 10495 0.0023401 0.0351671
0.7500000 8 0.0000018 0.0000268
1.0000000 129692 0.0289172 0.4345781

Length of periods with missing observations

In this section, we explore the length of periods with missing observations. This length may provide information on causes of missingness. Missing observations for long periods of time may be indicative of cluttered filters of broken instrument. We also explore whether the length of missingness patterns is correlated with weather variables.

First, we explore the length of missing observations by looking at the displaying, in an heatmat, for each couple station*date, whether concentration data is missing. We break this down into years for readibility.

[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

Then, we look at the length of periods with missing data. First, we can either count each the number of periods with a given length (eg 3 periods have a length of missing data of 5 hours) or count the number of dates belonging to periods with a given length (considering the same example, 15 dates belong to a period of missing data of length 5 hours). We denote the former case “One observation per period” and the later “One observation per date”.

Distribution of lengths of missing data

LS0tCnRpdGxlOiAiQW5hbHlzaXMgb2YgbWlzc2luZyBkYXRhIHBhdHRlcm5zIgphdXRob3I6CiAgLSBuYW1lOiBWaW5jZW50IEJhZ2lsZXQgCiAgICB1cmw6IGh0dHBzOi8vd3d3LnNpcGEuY29sdW1iaWEuZWR1L2V4cGVyaWVuY2Utc2lwYS9zaXBhLXByb2ZpbGVzL3ZpbmNlbnQtYmFnaWxldAogICAgYWZmaWxpYXRpb246IENvbHVtYmlhIFVuaXZlcnNpdHkKICAgIGFmZmlsaWF0aW9uX3VybDogaHR0cHM6Ly93d3cuY29sdW1iaWEuZWR1LwogIC0gbmFtZTogTMOpbyBaYWJyb2NraSAKICAgIHVybDogaHR0cHM6Ly93d3cucGFyaXNzY2hvb2xvZmVjb25vbWljcy5ldS9lbi8KICAgIGFmZmlsaWF0aW9uOiBQYXJpcyBTY2hvb2wgb2YgRWNvbm9taWNzCiAgICBhZmZpbGlhdGlvbl91cmw6IGh0dHBzOi8vd3d3LnBhcmlzc2Nob29sb2ZlY29ub21pY3MuZXUvZW4vCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IG5vCiAgICB0aGVtZTogc2ltcGxleAogICAgaGlnaGxpZ2h0OiBweWdtZW50cwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogc2ltcGxleAogICAgaGlnaGxpZ2h0OiBweWdtZW50cwotLS0KPCEtLSBvdXRwdXQ6IGRpc3RpbGw6OmRpc3RpbGxfYXJ0aWNsZSAtLT4KPCEtLSAtLS0gLS0+Cgo8c3R5bGU+CmJvZHkgewp0ZXh0LWFsaWduOiBqdXN0aWZ5fQo8L3N0eWxlPgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQpvcHRzX2NodW5rJHNldChmaWcucGF0aCA9ICJpbWFnZXMvIiwKICAgICAgICAgICAgICAgY2FjaGUucGF0aCA9ICJjYWNoZS8iLAogICAgICAgICAgICAgICBjYWNoZSA9IEZBTFNFLAogICAgICAgICAgICAgICBlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLAogICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsCiAgICAgICAgICAgICAgIG91dC53aWR0aCA9ICI3MCUiLAogICAgICAgICAgICAgICBkcGkgPSAzMDAsCiAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiKSAgCmBgYCAgCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShtZWRpb2NyZXRoZW1lcykKIyBsaWJyYXJ5KG1hcHMpCmxpYnJhcnkobHVicmlkYXRlKQojIGxpYnJhcnkobGVhZmxldCkKCnNldF9tZWRpb2NyZV9hbGwoKQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9Cm1ldGFkYXRhX3BvbGx1dGlvbiA8LSByZWFkUkRTKCIuLi9PdXRwdXRzL2NsZWFuX21ldGFkYXRhX3BvbGx1dGlvbi5SRFMiKQpkYXRhX2ltcHV0YXRpb24gPC0gcmVhZFJEUygiLi4vT3V0cHV0cy9kYXRhX2ltcHV0YXRpb24uUkRTIikKIyByYXcgPC0gcmVhZFJEUygiLi4vT3V0cHV0cy9yYXdfYWlyX3BvbGx1dGlvbl9kYXRhLlJEUyIpCmBgYAoKSW4gdGhpcyBkb2N1bWVudCwgd2UgYW5hbHlzZSBtaXNzaW5nIGRhdGEgcGF0dGVybnMgaW4gdGhlIGRhdGFzZXQuIAoKRmlyc3Qgb2YgYWxsLCB3ZSBub3RpY2VkIHRoYXQgdGhlcmUgYXJlIHNvbWUgaXNzdWVzIHdpdGggdGhlIGRhdGFzZXQgYW5kIHRoZXJlZm9yZSwgZm9yIG5vdywgd2UgcmVzdHJpY3QgdGhlIGRhdGFzZXQgdG8gb2JzZXJ2YXRpb25zIG5vdCBzdWJqZWN0IHRvIHRoZXNlIGlzc3Vlcy4gSW4gcGFydGljdWxhciwgd2UgZG8gbm90IGhhdmUgYW55IHBvbGx1dGlvbiBkYXRhIGZvciAyMDE0IG5vciBmb3IgTk8gaW4gMjAxNSBhbmQgdmVyeSBmZXcgb2JzZXJ2YXRpb25zIGZvciBQTXMgaW4gMjAxOS4gVGhlc2UgaXNzdWUgZG8gbm90IGNvbWUgZnJvbSBhY3R1YWwgbWlzc2luZyBkYXRhIGJ1dCBhcmUgZHVlIHRvIGlzc3VlIHdpdGggdGhlIHBhY2thZ2Ugd2UgdXNlZCB0byBhY2Nlc3MgdGhlIHBvbGx1dGlvbiBkYXRhLiBUaGVzZSBkYXRhIGFyZSBhdmFpbGFibGUgdGhyb3VnaCB0aGUgRUVBIGludGVyZmFjZS4KCmBgYHtyfQpkYXRhIDwtIGRhdGFfaW1wdXRhdGlvbiAlPiUgIAogIG11dGF0ZSgKICAgIHllYXIgPSBhcy5mYWN0b3IoeWVhcihkYXRlKSksCiAgICBtb250aCA9IGFzLmZhY3Rvcihtb250aChkYXRlKSksCiAgICBkYXlfb2ZfbW9udGggPSBhcy5mYWN0b3IoZGF5KGRhdGUpKSwKICAgIGRheV9pbl93ZWVrID0gYXMuZmFjdG9yKHdkYXkoZGF0ZSkpLAogICAgaG91ciA9IGFzLmZhY3Rvcihob3VyKGRhdGUpKSwKICAgIG1pc3NpbmcgPSBpcy5uYShjb25jZW50cmF0aW9uKQogICkgJT4lIAogIGZpbHRlcih5ZWFyICE9IDIwMTQpICU+JSAKICBmaWx0ZXIoISh5ZWFyID09IDIwMTUgJiBwb2xsdXRhbnQgPT0gIm5vIikpICU+JSAKICBmaWx0ZXIoISh5ZWFyID09IDIwMTkgJiBzdHJfc3ViKHBvbGx1dGFudCwgMSwgMikgPT0gInBtIikpIAogIAogIApybShkYXRhX2ltcHV0YXRpb24pCmBgYAoKCiMgU2hhcmUgb2YgbWlzc2luZyBkYXRhIGluIGNvdmFyaWF0ZXMKCmBgYHtyfQpkYXRhICU+JSAKICBzZWxlY3QoLShwb2xsdXRhbnQ6YXZlcmFnaW5nX3RpbWUpLCAtY29uY2VudHJhdGlvbiwgLSh5ZWFyOmhvdXIpKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgc3VtbWFyaXNlX2FsbChmdW5jdGlvbih4KSB7c3VtKGlzLm5hKHgpLCBuYS5ybSA9IFRSVUUpL24oKX0pICU+JSAKICBwaXZvdF9sb25nZXIoZXZlcnl0aGluZygpLCBuYW1lc190byA9ICJ2YXJpYWJsZV9uYW1lIiwgdmFsdWVzX3RvID0gInByb3BfbWlzc2luZyIpICU+JQogIG11dGF0ZSh2YXJpYWJsZV9uYW1lID0gc3RyX3JlcGxhY2VfYWxsKHZhcmlhYmxlX25hbWUsIHBhdHRlcm4gPSAiXyIsIHJlcGxhY2VtZW50ID0gIiAiKSAlPiUgc3RyX3RvX3NlbnRlbmNlKCkpICU+JSAKICBrYWJsZShjb2wubmFtZXMgPSBjKCJWYXJpYWJsZSIsICJQcm9wb3J0aW9uIG9mIG1pc3NpbmcgdmFsdWVzIikpCmBgYAoKSW4gb3JkZXIgdG8gdW5kZXJzdGFuZCB0aGVzZSBwcmV2aW91cyByZXN1bHRzLCB3ZSBicmVhayBkb3duIHRoZSBhbmFseXNpcyBieSB5ZWFyIGFuZCByZXByZXNlbnQgdGhlIHJlc3VsdHMgaW4gYSBncmFwaCwgZm9yIHJlYWRhYmlsaXR5LgoKYGBge3J9CmNvdmFyX21pc3NpbmdfeWVhciA8LSBkYXRhICU+JSAKICAjIHNsaWNlKDE6MTAwMDApICU+JQogIHNlbGVjdCgtKHBvbGx1dGFudDphdmVyYWdpbmdfdGltZSksIC1jb25jZW50cmF0aW9uLCAtKG1vbnRoOmhvdXIpKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgZ3JvdXBfYnkoeWVhcikgJT4lIAogICMgbXV0YXRlX2FsbChpcy5uYSkgJT4lIAogIHN1bW1hcmlzZV9hbGwoZnVuY3Rpb24oeCkge3N1bShpcy5uYSh4KSwgbmEucm0gPSBUUlVFKS9uKCl9KSAlPiUKICBwaXZvdF9sb25nZXIoMjpsYXN0X2NvbCgpLCBuYW1lc190byA9ICJ2YXJpYWJsZV9uYW1lIiwgdmFsdWVzX3RvID0gInByb3BfbWlzc2luZyIpCgpjb3Zhcl9taXNzaW5nX3llYXIgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fY29sKGFlcyh4ID0gdmFyaWFibGVfbmFtZSwgIHkgPSBwcm9wX21pc3NpbmcsIGZpbGwgPSB5ZWFyKSwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKHRpdGxlID0gIlByb3BvcnRpb24gb2YgbWlzc2luZyBkYXRhIGJ5IGNvdmFyaWF0ZSIsIHN1YnRpdGxlID0gIkJ5IHllYXIiLCB5ID0gIlByb3BvcnRpb24gb2YgbWlzc2luZyBkYXRhIiwgeCA9ICIiKQpgYGAKCkluIGNvbXBsZXRlIGNhc2UgYW5hbHlzZXMsIG9ic2VydmF0aW9ucyBmb3Igd2hpY2ggYW55IHZhcmlhYmxlIGlzIG1pc3NpbmcgYXJlIGRyb3BwZWQuIE9uZSBtYXkgdGhlcmVmb3JlIHdvbmRlciB3aGF0IGlzIHRoZSBzaGFyZSBvZiBkcm9wcGVkIG9ic2VydmF0aW9ucyBpbiBhIGNvbXBsZXRlIGNhc2UgYW5hbHlzaXMuIFdlIG9ubHkgY29uc2lkZXIgdmFyaWFibGVzIHdoaWNoIGFyZSBwb3RlbnRpYWxseSByZWxldmFudC4gV2UgYWxzbyBkcm9wIHRoZSBVViByYWRpYXRpb24gdmFyaWFibGUgZHVlIHRvIGl0cyBsYXJnZSBzaGFyZSBvZiBtaXNzaW5nbmVzcy4KCmBgYHtyIGluY2x1ZGU9RkFMU0V9CmFueV9taXNzaW5nX2NvdiA8LSBkYXRhICU+JSAKICBzZWxlY3QoZWxldmF0aW9uOnB1YmxpY19ob2xpZGF5LCAtbGF0aXR1ZGVfd2VhdGhlcl9zdGF0aW9uLCAtbG9uZ2l0dWRlX3dlYXRoZXJfc3RhdGlvbiwgLXV2X3JhZGlhdGlvbikgJT4lIAogIG11dGF0ZV9hbGwoaXMubmEpICU+JSAKICB0cmFuc211dGUoYW55X21pc3NpbmcgPSAocm93U3VtcyguKSA+IDApKSAlPiUgCiAgLiRhbnlfbWlzc2luZwoKcHJvcF9jb3Zhcl9taXNzaW5nIDwtIHN1bShhbnlfbWlzc2luZ19jb3YpL2xlbmd0aChhbnlfbWlzc2luZ19jb3YpCgpwcm9wX3RvdGFsX21pc3NpbmcgPC0gc3VtKGFueV9taXNzaW5nX2NvdiArIGRhdGEkbWlzc2luZykvbGVuZ3RoKGFueV9taXNzaW5nX2NvdikKYGBgCgpDYXJyeWluZyBvdXQgYSBjb21wbGV0ZSBjYXNlIGFuYWx5c2lzIHdvdWxkIGxlYWQgdG8gZHJvcCBgciBwcm9wX3RvdGFsX21pc3NpbmcqMTAwYCUgb2YgdGhlIG9ic2VydmF0aW9ucy4gT25seSBjb25zaWRlcmluZyBtaXNzaW5nIGNvdmFyaWF0ZXMgKGFuZCBub3QgbWlzc2luZ25lc3MgaW4gY29uY2VudHJhdGlvbiBkYXRhKSB3b3VsZCBsZWFkIHRvIGRyb3AgYHIgcHJvcF9jb3Zhcl9taXNzaW5nKjEwMGAlIG9mIHRoZSBvYnNlcnZhdGlvbnMuCgojIExvY2F0aW9uIG9mIG1lYXN1cmVtZW50IHN0YXRpb25zCgpUaGUgc3RhdGlvbnMgY29uc2lkZXJlZCBhcmUgbG9jYXRlZCBpbiB0aGUgMTcgYmlnZ2VzdCBsYXJnZXN0IGluIEZyYW5jZToKCmBgYHtyfQptZXRhZGF0YV9wb2xsdXRpb24gJT4lIAogIGNvdW50KGNpdHkpICU+JSAKICBrYWJsZShjb2wubmFtZXMgPSBjKCJDaXR5IiwgIk51bWJlciBvZiBzdGF0aW9ucyIpKQpgYGAKCiMgTWlzc2luZyBkYXRhIHBhdHRlcm5zIGluIGFpciBwb2xsdXRpb24gZGF0YQoKSGVyZSwgd2UgaW52ZXN0aWdhdGUgd2hldGhlciBtaXNzaW5nIHBvbGx1dGFudCBjb25jZW50cmF0aW9uIGRhdGEgdmFyaWVzIGFjcm9zcyBkaWZmZXJlbnQgZGltZW50aW9ucy4gCgpgYGB7ciBpbmNsdWRlID0gRkFMU0V9CnNoYXJlX21pc3NpbmcgPC0gc3VtKGlzLm5hKGRhdGEkY29uY2VudHJhdGlvbikpL25yb3coZGF0YSkKYGBgCgpUaGUgb3ZlcmFsbCBzaGFyZSBvZiBtaXNzaW5nIHZhbHVlcyBpcyBgciBzaGFyZV9taXNzaW5nYC4KCiMjIEJhbGFuY2UgZ3JhaHMKCndlIGZpcnN0IGludmVzdGlnYXRlIHdoZXRoZXIgY292YXJpYXRlcyBhcmUgYmFsbGFuY2VkIGJldHdlZW4gb2JzZXJ2YXRpb25zIGZvciB3aGljaCBjb25jZW50cmF0aW9uIGRhdGEgaXMgbWlzc2luZyBhbmQgbm9uIG1pc3NpbmcuIAoKYGBge3J9CmRhdGFfY2xlYW5fY29udGludW91cyA8LSBkYXRhICU+JQogIHNlbGVjdChlbGV2YXRpb246ZWxldmF0aW9uX3dlYXRoZXJfc3RhdGlvbiwgcmFpbmZhbGxfaGVpZ2h0OnNjaG9vbF9ob2xpZGF5LCBtaXNzaW5nKQoKIyB3ZSBjb21wdXRlIHRoZSBhYnNvbHV0ZSBkaWZmZXJlbmNlIGJldHdlZW4gbm9uLW1pc3NpbmcgYW5kIG1pc3Npbmcgb2JzZXJ2YXRpb25zCmRhdGFfYWJzX2RpZmZlcmVuY2UgPC0gZGF0YV9jbGVhbl9jb250aW51b3VzICU+JQogIGdyb3VwX2J5KG1pc3NpbmcpICU+JQogIHN1bW1hcmlzZV9hbGwoLiwgfiBtZWFuKC4sIG5hLnJtID0gVFJVRSkpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gLWMobWlzc2luZyksIG5hbWVzX3RvID0gInZhcmlhYmxlIiwgdmFsdWVzX3RvID0gImF2ZXJhZ2UiKSAlPiUKICBhcnJhbmdlKHZhcmlhYmxlKSAlPiUKICBncm91cF9ieSh2YXJpYWJsZSkgJT4lCiAgc3VtbWFyaXNlKGFic19kaWZmZXJlbmNlID0gYWJzKGF2ZXJhZ2VbMl0gLSBhdmVyYWdlWzFdKSkKCiMgd2UgY29tcHV0ZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBub24tbWlzc2luZyB2YXJpYWJsZXMKZGF0YV9zZCA8LSBkYXRhX2NsZWFuX2NvbnRpbnVvdXMgJT4lCiAgZmlsdGVyKG1pc3NpbmcgPT0gRkFMU0UpICU+JQogIHNlbGVjdCgtbWlzc2luZykgJT4lCiAgc3VtbWFyaXNlX2FsbCguLCB+IHNkKC4sIG5hLnJtID0gVFJVRSkpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gZXZlcnl0aGluZygpLCBuYW1lc190byA9ICJ2YXJpYWJsZSIsIHZhbHVlc190byA9ICJzZF9ub25fbWlzc2luZyIpCgojIHdlIGNyZWF0ZSB0aGUgZGF0YSBmb3IgdGhlIGxvdmUgcGxvdCA6IHdlIHNjYWxlIHRoZSBhYnNvbHV0ZSBkaWZmZXJlbmNlIGJ5IHRoZSBzZF9ub25fbWlzc2luZwpkYXRhX2Fic19kaWZmZXJlbmNlICU+JSAKICBsZWZ0X2pvaW4oZGF0YV9zZCwgYnkgPSBjKCJ2YXJpYWJsZSIpKSAlPiUKICBtdXRhdGUoc3RhbmRhcmRpemVkX2RpZmZlcmVuY2UgPSBhYnNfZGlmZmVyZW5jZS9zZF9ub25fbWlzc2luZykgJT4lCiAgc2VsZWN0KC1jKGFic19kaWZmZXJlbmNlLCBzZF9ub25fbWlzc2luZykpICU+JSAKICBmaWx0ZXIoIWlzLm5hKHN0YW5kYXJkaXplZF9kaWZmZXJlbmNlKSkgJT4lIAogIGdncGxvdChhZXMoeSA9IGZjdF9yZXYodmFyaWFibGUpLCB4ID0gc3RhbmRhcmRpemVkX2RpZmZlcmVuY2UpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuMSwgY29sb3IgPSAiI0ZBQjczNyIpICsKICBnZW9tX3BvaW50KCkgKwogICMgZmFjZXRfd3JhcCh+IGNpdHkpICsKICBsYWJzKHRpdGxlID0gIkNvdmFyaWF0ZSBiYWxhbmNlIiAsIHggPSAiU3RhbmRhcmRpemVkIE1lYW4gRGlmZmVyZW5jZXMiLCB5ID0gIiIpCgpgYGAKCkl0IHNlZW1zIHRoYXQgbW9zdCB3ZWF0aGVyIGNvdmFyaWF0ZXMgYXJlIGJhbGFuY2VkIGJldHdlZW4gdGhlIHR3byBncm91cHMuIEF2ZXJhZ2UgdGVtcGVyYXR1cmUgYW5kIFVWIHJhZGlhdGlvbiBtYXkgaG93ZXZlciBiZSBzbGlnaHRseSBkaWZmZXJlbnQgYmV0d2VlbiB0aGUgdHdvIGdyb3Vwcy4KCldlIGNhbiByZWZpbmUgdGhpcyBhbmFseXNpcyBieSBsb29raW5nIHNlcGFyYXRlbHkgYWNyb3NzIGNpdGllcy4KCmBgYHtyfQpkYXRhX2NsZWFuX2NvbnRpbnVvdXMgPC0gZGF0YSAlPiUKICBzZWxlY3QoZWxldmF0aW9uOmVsZXZhdGlvbl93ZWF0aGVyX3N0YXRpb24sIHJhaW5mYWxsX2hlaWdodDpzY2hvb2xfaG9saWRheSwgbWlzc2luZywgY2l0eSkKCiMgd2UgY29tcHV0ZSB0aGUgYWJzb2x1dGUgZGlmZmVyZW5jZSBiZXR3ZWVuIG5vbi1taXNzaW5nIGFuZCBtaXNzaW5nIG9ic2VydmF0aW9ucwpkYXRhX2Fic19kaWZmZXJlbmNlIDwtIGRhdGFfY2xlYW5fY29udGludW91cyAlPiUKICBncm91cF9ieShjaXR5LCBtaXNzaW5nKSAlPiUKICBzdW1tYXJpc2VfYWxsKC4sIH4gbWVhbiguLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC1jKGNpdHksIG1pc3NpbmcpLCBuYW1lc190byA9ICJ2YXJpYWJsZSIsIHZhbHVlc190byA9ICJhdmVyYWdlIikgJT4lCiAgYXJyYW5nZShjaXR5LCB2YXJpYWJsZSkgJT4lCiAgZ3JvdXBfYnkoY2l0eSwgdmFyaWFibGUpICU+JQogIHN1bW1hcmlzZShhYnNfZGlmZmVyZW5jZSA9IGFicyhhdmVyYWdlWzJdIC0gYXZlcmFnZVsxXSkpCgojIHdlIGNvbXB1dGUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgbm9uLW1pc3NpbmcgdmFyaWFibGVzCmRhdGFfc2QgPC0gZGF0YV9jbGVhbl9jb250aW51b3VzICU+JQogIGZpbHRlcihtaXNzaW5nID09IEZBTFNFKSAlPiUKICBzZWxlY3QoLW1pc3NpbmcpICU+JQogIGdyb3VwX2J5KGNpdHkpICU+JQogIHN1bW1hcmlzZV9hbGwoLiwgfiBzZCguLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC1jKGNpdHkpLCBuYW1lc190byA9ICJ2YXJpYWJsZSIsIHZhbHVlc190byA9ICJzZF9ub25fbWlzc2luZyIpCgojIHdlIGNyZWF0ZSB0aGUgZGF0YSBmb3IgdGhlIGxvdmUgcGxvdCA6IHdlIHNjYWxlIHRoZSBhYnNvbHV0ZSBkaWZmZXJlbmNlIGJ5IHRoZSBzZF9ub25fbWlzc2luZwpkYXRhX2Fic19kaWZmZXJlbmNlICU+JSAKICBsZWZ0X2pvaW4oZGF0YV9zZCwgYnkgPSBjKCJjaXR5IiwgInZhcmlhYmxlIikpICU+JQogIG11dGF0ZShzdGFuZGFyZGl6ZWRfZGlmZmVyZW5jZSA9IGFic19kaWZmZXJlbmNlL3NkX25vbl9taXNzaW5nKSAlPiUKICBzZWxlY3QoLWMoYWJzX2RpZmZlcmVuY2UsIHNkX25vbl9taXNzaW5nKSkgJT4lIAogIGZpbHRlcighaXMubmEoc3RhbmRhcmRpemVkX2RpZmZlcmVuY2UpKSAlPiUgCiAgZ2dwbG90KGFlcyh5ID0gZmN0X3Jldih2YXJpYWJsZSksIHggPSBzdGFuZGFyZGl6ZWRfZGlmZmVyZW5jZSkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC4xLCBjb2xvciA9ICIjRkFCNzM3IikgKwogIGdlb21fcG9pbnQoKSArCiAgZmFjZXRfd3JhcCh+IGNpdHkpICsKICBsYWJzKHRpdGxlID0gIkNvdmFyaWF0ZSBiYWxhbmNlIiAsIHggPSAiU3RhbmRhcmRpemVkIE1lYW4gRGlmZmVyZW5jZXMiLCB5ID0gIiIpCgpgYGAKCiMjIEV2b2x1dGlvbiBvZiB0aGUgc2hhcmUgb2YgbWlzc2luZyB2YWx1ZXMgd2l0aCB0aGUgdmFsdWVzIG9mIGNvdmFyaWF0ZXMKCkluIHRoaXMgc2VjdGlvbiwgd2UgaW52ZXN0aWdhdGUgd2hldGhlciB0aGUgc2hhcmUgb2YgbWlzc2luZyB2YWx1ZXMgdmFyaWVzIHdpdGggdGhlIHZhbHVlcyBvZiBjb3ZhcmlhdGVzLiBPbmUgbWF5IGV4cGVjdCB0aGF0LCBmb3IgZXh0cmVtZSB2YWx1ZXMgb2Ygc29tZSBjb3ZhcmlhdGVzLCBzdWNoIGFzIHRlbXBlcmF0dXJlLCB3aW5kIHNwZWVkIG9yIHByZWNpcGl0YXRpb24gbGV2ZWwgZm9yIGV4YW1wbGUsIG1lYXN1cmVtZW50IGluc3RydW1lbnRzIGFyZSBtb3JlIGxpa2VseSB0byBiZSBkZWZlY3RpdmUsIGxlYWRpbmcgdG8gbW9yZSBtaXNzaW5nIHZhbHVlcy4KCgpgYGB7cn0KIycgR3JhcGhzIGRlc2NyaWJpbmcgdGhlIHByb3BvcnRpb24gb2YgbWlzc2luZyB2YWx1ZXMgaW4gZGlmZmVyZW50IGdyb3VwcwojJwojJyBFbmFibGVzIHRvIHBsb3QgdGhlIHByb3BvcnRpb24gb2YgbWlzc2luZyB2YWx1ZXMgYnkgYSBudW1iZXIgb2YgCiMnCiMnIEBwYXJhbSBkZiBBIGRhdGFmcmFtZS4gRGF0YWZyYW1lIHRvIGFuYWx5c2UgCiMnIEBwYXJhbSBncm91cGluZ192YXIgQSBzdHJpbmcuIE5hbWUgb2YgdGhlIHZhcmlhYmxlLCBpbiBcY29kZXtkZn0sIGZvciB3aGljaCB0aGUgcHJvcG9ydGlvbiBvZiBtaXNzaW5nIHZhbHVlcyBuZWVkcyB0byBiZSBkaXNwbGF5ZWQKIycgQHBhcmFtIGJpbnMgQW4gaW50ZWdlci4gTnVtYmVyIG9mIGJpbnMgdG8gc2xpY2UgXGNvZGV7Z3JvdXBpbmdfdmFyfSBpbiwgaWYgaXQgaXMgYSBjb250aW51b3VzIHZhbHVlLgojJyBAcGFyYW0gZmFjZXRfdmFyIEEgc3RyaW5nLiBOYW1lIG9mIHRoZSB2YXJpYWJsZSwgaW4gXGNvZGV7ZGZ9LCBieSB3aGljaCB0byBmYWNldCB0aGUgaW5pdGlhbCBncmFwaAojJyBAcGFyYW0geV9heGlzX3RvIEFuIGludGVnZXIuIExpbWl0IG9mIHRoZSB5IGF4aXMKIycgQGV4cG9ydAojJwpoaXN0X21pc3NpbmdfYnkgPC0gZnVuY3Rpb24oZGYsIHZhcmlhYmxlX21pc3NpbmcgPSAiY29uY2VudHJhdGlvbiIsIGdyb3VwaW5nX3ZhciwgYmlucyA9IDE1LCBmYWNldF92YXIgPSBOQSwgZmlsbF92YXIgPSBOQSwgeV9heGlzX3RvID0gMC4zKSB7CiAgCiAgZ3JvdXBpbmdfdmFyX25hbWUgPC0gc3RyX3JlcGxhY2VfYWxsKGdyb3VwaW5nX3ZhciwgcGF0dGVybiA9ICJfIiwgcmVwbGFjZW1lbnQgPSAiICIpCiAgdmFyaWFibGVfbWlzc2luZ19uYW1lIDwtIHN0cl9yZXBsYWNlX2FsbCh2YXJpYWJsZV9taXNzaW5nLCBwYXR0ZXJuID0gIl8iLCByZXBsYWNlbWVudCA9ICIgIikKICAKICBpZiAoIWlzLmZhY3RvcihkZltbZ3JvdXBpbmdfdmFyXV0pICYmICFpcy5sb2dpY2FsKGRmW1tncm91cGluZ192YXJdXSkgICYmICFpcy5uYShhcy5udW1lcmljKGRmW1tncm91cGluZ192YXJdXSkpKSB7CiAgICBkZltbZ3JvdXBpbmdfdmFyXV0gPC0gY3V0X2ludGVydmFsKGFzLm51bWVyaWMoZGZbW2dyb3VwaW5nX3Zhcl1dKSwgYmlucykKICB9IAogIAogIGdyYXBoIDwtIGRmICU+JSAKICAgIGZpbHRlcighaXMubmEoLmRhdGFbW2dyb3VwaW5nX3Zhcl1dKSkgJT4lIAogICAgZ3JvdXBfYnlfKGdyb3VwaW5nX3ZhciwgZmFjZXRfdmFyLCBmaWxsX3ZhcikgJT4lCiAgICBzdW1tYXJpc2Uoc2hhcmVfbWlzc2luZyA9IHN1bShpcy5uYSguZGF0YVtbdmFyaWFibGVfbWlzc2luZ11dKSkvbigpKSAlPiUKICAgIGFycmFuZ2Uoc2hhcmVfbWlzc2luZykgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSAuZGF0YVtbZ3JvdXBpbmdfdmFyXV0sIHkgPSBzaGFyZV9taXNzaW5nKSkgKwogICAgZ2VvbV9jb2woYWVzX3N0cmluZyhmaWxsID0gaWZlbHNlKCFpcy5uYShmaWxsX3ZhciksIGZpbGxfdmFyLCAiTlVMTCIpKSwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgICBsYWJzKAogICAgICB0aXRsZSA9IHBhc3RlKCJTaGFyZSBvZiBtaXNzaW5nIiwgdmFyaWFibGVfbWlzc2luZ19uYW1lLCJkYXRhIGJ5IiwgZ3JvdXBpbmdfdmFyX25hbWUpLAogICAgICB4ID0gc3RyX3RvX3NlbnRlbmNlKGdyb3VwaW5nX3Zhcl9uYW1lKSwgCiAgICAgIHkgPSBwYXN0ZSgiU2hhcmUgb2YgbWlzc2luZyIsIHZhcmlhYmxlX21pc3NpbmdfbmFtZSwiZGF0YSIpCiAgICApIAogIAogIGlmICghaXMubnVsbCh5X2F4aXNfdG8pKSB7CiAgICBncmFwaCA8LSBncmFwaCArIAogICAgICB5bGltKDAsIHlfYXhpc190bykgCiAgfQogICAKICBpZiAoIWlzLm5hKGZhY2V0X3ZhcikpIHsKICAgIGdyYXBoIDwtIGdyYXBoICsKICAgIGZhY2V0X3dyYXAoZmFjZXRzID0gZmFjZXRfdmFyKQogIH0gCiAgCiAgaWYgKHN1YnN0cihncm91cGluZ192YXIsIDEsIDgpID09ICJ3aW5kX2RpciIpIHsKICAgIGdyYXBoIDwtIGdyYXBoICsKICAgICAgY29vcmRfcG9sYXIoKSArIAogICAgICB5bGltKDAsIDAuMSkgCiAgfQogIAogIAogIHJldHVybihncmFwaCkKfQpgYGAKCiMjIyBBY3Jvc3MgcG9sbHV0YW50cwoKYGBge3J9CmRhdGEgJT4lICAKICBoaXN0X21pc3NpbmdfYnkoZ3JvdXBpbmdfdmFyID0gInBvbGx1dGFudCIpIApgYGAKCk9uZSBjYW4gbm90aWNlIHRoYXQgdGhlIHNoYXJlIG9mIG1pc3NpbmcgdmFsdWVzIHZhcmllcyBhY3Jvc3MgcG9sbHV0YW50cywgdXAgdG8gYWJvdXQgYSBmYWN0b3IgdHdvLiBUaGlzIGhpZ2xpZ2h0cyB0aGUgcG90ZW50aWFsIG5lY2Vzc2l0eSBvZiBhbmFseXNpbmcgbWlzc2luZ25lc3MgcGF0dGVybnMgaW5kZXBlbmRlbnRseSBhY3Jvc3MgcG9sbHV0YW50cy4KCiMjIyBBY3Jvc3MgbG9jYXRpb25zCgpXZSBsb29rIHdlYXRoZXIgbWlzc2luZ25lc3MgcGF0dGVybnMgdmFyeSBhY3Jvc3MgbG9jYXRpb24gY2hhcmFjdGVyaXN0aWNzLgoKYGBge3J9CmNvdmFyaWF0ZXNfbG9jYXRpb24gPC0gZGF0YSAlPiUgCiAgc2VsZWN0KGVsZXZhdGlvbjplbGV2YXRpb25fd2VhdGhlcl9zdGF0aW9uKSAlPiUgCiAgbmFtZXMoKQoKcHVycnI6Om1hcChjb3ZhcmlhdGVzX2xvY2F0aW9uLCBoaXN0X21pc3NpbmdfYnksIGRmID0gZGF0YSwgdmFyaWFibGVfbWlzc2luZyA9ICJjb25jZW50cmF0aW9uIiwgYmlucyA9IDEwLCBmYWNldF92YXIgPSBOQSwgZmlsbCA9IE5BLCB5X2F4aXNfdG8gPSAwLjMpCgpkYXRhICU+JQogIGhpc3RfbWlzc2luZ19ieShncm91cGluZ192YXIgPSAiY2l0eSIpICsKICBjb29yZF9mbGlwKCkKYGBgCgojIyMgQWNyb3NzIGRhdGVzIGFuZCB0aW1lCgpXZSB0aGVuIGludmVzdGlnYXRlIHdoZXRoZXIgdGhlIHNoYXJlIG9mIG1pc3NpbmcgdmFsdWVzIGV2b2x2ZXMgd2l0aCBkYXRlcyBhbmQgdGltZS4KCmBgYHtyfQpjb3ZhcmlhdGVzX3RpbWUgPC0gZGF0YSAlPiUgCiAgc2VsZWN0KHB1YmxpY19ob2xpZGF5OmhvdXIpICU+JSAKICBuYW1lcygpCgpwdXJycjo6bWFwKGNvdmFyaWF0ZXNfdGltZSwgaGlzdF9taXNzaW5nX2J5LCBkZiA9IGRhdGEsIHZhcmlhYmxlX21pc3NpbmcgPSAiY29uY2VudHJhdGlvbiIsIGJpbnMgPSAxNSwgZmFjZXRfdmFyID0gTkEsIGZpbGwgPSBOQSwgeV9heGlzX3RvID0gMC4zKQpgYGAKCk92ZXJhbGwsIHdlIG5vdGljZSB0aGF0LCBhbG9uZyB0aGUgdGltZSBkaW1lbnNpb24gZGF0YSBhbG1vc3Qgc2VlbXMgdG8gYmUgbWlzc2luZyBhdCByYW5kb20gYXBwYXJ0IGZyb20gYSBkZWNyZWFzaW5nIHRyZW5kIGluIHRoZSBwcm9wb3J0aW9uIG9mIG1pc3NpbmcgZGF0YSAKCldlIGFsc28gZXhwbG9yZSBtb3JlIGNsb3NlbHkgdGhlc2UgcGF0dGVybnMgZm9yIHNvbWUgdmFyaWFibGVzIGJ5IGRlY29tcG9zaW5nIHRoZW0gYnkgeWVhciwgbW9udGggb3IgcG9sbHV0YW50LgoKYGBge3J9CmRhdGEgJT4lICAKICBoaXN0X21pc3NpbmdfYnkoZ3JvdXBpbmdfdmFyID0gIm1vbnRoIiwgZmFjZXRfdmFyID0gInllYXIiKQoKZGF0YSAlPiUgIAogIGhpc3RfbWlzc2luZ19ieShncm91cGluZ192YXIgPSAiZGF5X29mX21vbnRoIiwgZmFjZXRfdmFyID0gInllYXIiKQoKZGF0YSAlPiUgIAogIGhpc3RfbWlzc2luZ19ieShncm91cGluZ192YXIgPSAiZGF5X29mX21vbnRoIiwgZmFjZXRfdmFyID0gIm1vbnRoIikKCmRhdGEgJT4lCiAgaGlzdF9taXNzaW5nX2J5KGdyb3VwaW5nX3ZhciA9ICJkYXlfaW5fd2VlayIsIGZhY2V0X3ZhciA9ICJ5ZWFyIikKCmRhdGEgJT4lCiAgaGlzdF9taXNzaW5nX2J5KGdyb3VwaW5nX3ZhciA9ICJkYXlfaW5fd2VlayIsIGZhY2V0X3ZhciA9ICJtb250aCIpCgpkYXRhICU+JQogIGhpc3RfbWlzc2luZ19ieShncm91cGluZ192YXIgPSAiaG91ciIsIGZhY2V0X3ZhciA9ICJwb2xsdXRhbnQiKQoKZGF0YSAlPiUKICBoaXN0X21pc3NpbmdfYnkoZ3JvdXBpbmdfdmFyID0gInllYXIiLCBmaWxsX3ZhciA9ICJwb2xsdXRhbnQiKQpgYGAKCiMjIyBBY3Jvc3Mgd2VhdGhlciB2YXJpYWJsZXMKCmBgYHtyfQpjb3ZhcmlhdGVzX3dlYXRoZXIgPC0gZGF0YSAlPiUgCiAgc2VsZWN0KHJhaW5mYWxsX2hlaWdodDp1dl9yYWRpYXRpb24pICU+JSAKICBuYW1lcygpCgpwdXJycjo6bWFwKGNvdmFyaWF0ZXNfd2VhdGhlciwgaGlzdF9taXNzaW5nX2J5LCBkZiA9IGRhdGEsIHZhcmlhYmxlX21pc3NpbmcgPSAiY29uY2VudHJhdGlvbiIsIGJpbnMgPSAxNSwgZmFjZXRfdmFyID0gTkEsIGZpbGwgPSBOQSwgeV9heGlzX3RvID0gMC4zKQpgYGAKCgojIyMgT25seSBjb25zaWRlciBmaXJzdCBtaXNzaW5nIHZhbHVlCgpJZiBkYXRhIGlzIG1pc3NpbmcgZHVlIHRvIGV4dGVybmFsIGZhY3RvcnMsIHdoYXQgbWF0dGVycyBtaWdodCBiZSB0aGUgdmFsdWUgb2YgdGhlc2UgZXh0ZXJuYWwgZmFjdG9yIHdoZW4gdGhlIGRhdGEgc3RhcnRlZCBtaXNzaW5nLCAqaWUqIHBvdGVudGlhbGx5IHdoZW4gdGhlIHNlbnNvciBmaXJzdCBiZWNhbWUgZGVmZWN0aXZlLiBBcyBhIGNvbnNlcXVlbmNlLCB3ZSBwbG90IHRoZSBzYW1lIGdyYXBocyBhcyBiZWZvcmUgYnV0IG9ubHkgY29uc2lkZXJpbmcgaG91cnMgd2VyZSB0aGUgZGF0YSBzdGFydGVkIG1pc3NpbmcsIG5vdCBjb25zaWRlcmluZyBsYXRlciBhbmQgY29uc2VjdXRpdmUgbWlzc2luZyBvYnNlcnZhdGlvbnMuCgpBcyBjb21wYXJlZCB0byB0aGUgZnVsbCBzYW1wbGUsIHRoZSBzaGFyZSBvZiBtaXNzaW5nIGRhdGEgZGVjcmVhc2VzIHNpbmNlIHdlIGRpc2NhcmRlZCBtYW55IG9ic2VydmF0aW9ucyB3aXRoIG1pc3NpbmcgdmFsdWVzIChldmVyeSBvYnNlcnZhdGlvbiB3aGljaCB3YXMgbm90IHRoZSBmaXJzdCBvYnNlcnZhdGlvbiBvZiB0aGVpciBwZXJpb2Qgb2YgbWlzc2luZyBkYXRhKS4gSGVuY2UsIHRoZSBzaGFyZSBvZiBtaXNzaW5nIGRhdGEgaXMgbm90IGluZm9ybWF0aXZlIGluIGl0c2VsZiwgb25seSBwb3RlbnRpYWwgZGlmZmVyZW5jZXMgaW4gdGhpcyBzaGFyZSBhY3Jvc3MgImdyb3VwaW5nIHZhcmlhYmxlcyIuCgpgYGB7cn0KZGF0YV9maXJzdF9taXNzaW5nIDwtIGRhdGEgJT4lICAKICBncm91cF9ieShzaXRlLCBwb2xsdXRhbnQpICU+JQogIGFycmFuZ2UoZGF0ZSkgJT4lIAogIG11dGF0ZSggCiAgICBmaXJzdF9taXNzaW5nID0gaWZlbHNlKG1pc3NpbmcgPT0gVFJVRSAmIGxhZyhtaXNzaW5nKSA9PSBGQUxTRSwgVFJVRSwgRkFMU0UpCiAgKSAlPiUKICBmaWx0ZXIoZmlyc3RfbWlzc2luZyB8IG1pc3NpbmcgPT0gRkFMU0UpCmBgYAoKCmBgYHtyfQpjb3ZhcmlhdGVfbmFtZXMgPC0gZGF0YSAlPiUgCiAgc2VsZWN0KGNpdHksIHBvbGx1dGFudCwgZWxldmF0aW9uOmhvdXIsIC1lbmRzX3dpdGgoIndlYXRoZXJfc3RhdGlvbiIpKSAlPiUgCiAgbmFtZXMoKQoKcHVycnI6Om1hcChjb3ZhcmlhdGVfbmFtZXMsIGhpc3RfbWlzc2luZ19ieSwgZGYgPSBkYXRhX2ZpcnN0X21pc3NpbmcsIHZhcmlhYmxlX21pc3NpbmcgPSAiY29uY2VudHJhdGlvbiIsIGJpbnMgPSAxMCwgZmFjZXRfdmFyID0gTkEsIHlfYXhpc190byA9IDAuMSkKYGBgCgojIyBTaW11bHRhbmVvdXMgbWlzc2luZ25lc3MKCkluIHRoaXMgc2VjdGlvbiwgd2UgYW5hbHlzZSB3aGV0aGVyIHNvbWUgcGF0dGVybnMgb2Ygc2ltdWx0YW5lb3VzIG1pc3NpbmduZXNzIGFwcGVhciBpbiB0aGUgZGF0YS4gV2Ugd29uZGVyIHdoZXRoZXIsIGZvciBhIGdpdmVuIHN0YXRpb24sIGRhdGEgaXMgc2ltdWx0YW5lb3VzbHkgbWlzc2luZyBmb3Igc2V2ZXJhbCBwb2xsdXRhbnRzIG9yIHdoZXRoZXIsIGZvciBhIGdpdmVuIGNpdHksIGRhdGEgaXMgc2ltdWx0YW5lb3VzbHkgbWlzc2luZyBmb3Igc2V2ZXJhbCBzdGF0aW9ucy4gCgojIyMgQWNyb3NzIHBvbGx1dGFudHMKCldlIGludmVzdGlnYXRlIHdoZXRoZXIsIGluIGEgZ2l2ZW4gc3RhdGlvbiwgd2hlbiBvbmUgcG9sbHV0YW50IGlzIG1pc3NpbmcsIG90aGVyIHBvbGx1dGFudHMgYXJlIGFsc28gbWlzc2luZy4gU3VjaCBhIG1pc3NpbmduZXNzIHBhdHRlcm4gY291bGQgYXJpc2UgaWYgc2Vuc29ycyBmb3IgZGlmZmVyZW50IHBvbGx1dGFudHMgZnVuY3Rpb24gam9pbnRseS4gCgpXZSBjb3VudCB0aGUgbnVtYmVyIG9mIHBvbGx1dGFudHMgd2hpY2ggYXJlIHNpbXVsdGFuZW91c2x5IG1pc3NpbmcgZm9yIGV2ZXJ5IHN0YXRpb24qZGF0ZSBjb3VwbGUuIE5vdGUgdGhhdCB0aGlzIGFuYWx5c2lzIGRvZXMgbm90IGNvbnNpZGVyIHRoYXQgYW4gb2JzZXJ2YXRpb24gaXMgbWlzc2luZyB3aGVuIGEgZ2l2ZW4gc3RhdGlvbiBpcyBjbG9zZWQgZm9yIGEgcG9sbHV0YW50LgoKYGBge3J9CmRhdGEgJT4lIAogIGdyb3VwX2J5KGRhdGUsIHNpdGUpICU+JSAKICBzdW1tYXJpc2UobmJfbWlzc2luZyA9IHN1bShtaXNzaW5nKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgY291bnQobmJfbWlzc2luZykgJT4lIAogIG11dGF0ZShwcm9wID0gbi9zdW0obikpICU+JSAKICBrYWJsZShjb2wubmFtZXMgPSBjKCJOdW1iZXIgb2YgcG9sbHV0YW50cyB3aXRoIG1pc3NpbmcgY29uY2VudHJhdGlvbiBkYXRhIiwgIk51bWJlciBvZiBkYXRlcyIsICJQcm9wb3J0aW9uIikpCmBgYAoKV2UgY291bGQgYWxzbyBpbnZlc3RpZ2F0ZSB3aGV0aGVyIHRoaXMgcGF0dGVybiB2YXJpZXMgd2l0aCB2YXJpb3VzIHdlYXRoZXIgdmFyaWFibGVzLgoKTm93LCBwYXJ0IG9mIHRoZSBzdGF0aW9ucyBkbyBub3QgbWVhc3VyZSB2YWx1ZXMgZm9yIGFsbCBwb2xsdXRhbnRzLiBUaHVzLCBpdCBpcyBpbnRlcmVzdGluZyB0byBjb21wdXRlIHRoZSBwcm9wb3J0aW9uIG9mIHBvbGx1dGFudHMgbWVhc3VyZWQgYnkgc3RhdGlvbiBmb3Igd2hpY2ggZGF0YSBpcyBtaXNzaW5nLgoKYGBge3J9CmRhdGEgJT4lIAogICMgbXV0YXRlKG9uZSA9IDEpICU+JSAKICBncm91cF9ieShkYXRlLCBzaXRlKSAlPiUgCiAgc3VtbWFyaXNlKHNoYXJlX21pc3NpbmcgPSBzdW0obWlzc2luZykvbigpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBjb3VudChzaGFyZV9taXNzaW5nKSAlPiUgCiAgbXV0YXRlKAogICAgcHJvcCA9IG4vc3VtKG4pLAogICAgcHJvcF9pZl9taXNzaW5nID0gaWZlbHNlKHNoYXJlX21pc3NpbmcgIT0gMCwgbi8oc3VtKG4pIC0gblsxXSksIE5BKQogICkgJT4lIAogIGthYmxlKGNvbC5uYW1lcyA9IGMoIlNoYXJlIG9mIHBvbGx1dGFudHMgbWVhc3VyZWQgaW4gdGhlIHN0YXRpb24gZm9yIHdoaWNoIGNvbmNlbnRyYXRpb24gZGF0YSBpcyBtaXNzaW5nIiwgIk51bWJlciBvZiBkYXRlcyIsICJQcm9wb3J0aW9uIiwgIlByb3BvcnRpb24gYW1vbmcgZGF0ZXMgd2l0aCBtaXNzaW5nIG9ic2VydmF0aW9ucyIpLCBjYXB0aW9uID0gIkluIGFsbCBzdGF0aW9ucyIpCmBgYAoKU2luY2UgZm9yIGFuYWx5c2VzIHN0dWR5aW5nIHRoZSBsaW5rIGJ0d2VlbiBhaXIgcG9sbHV0aW9uIGFuZCBoZWFsdGggaGF2ZSBhIHBhcnRpY3VsYXIgZm9jdXMgb24gYmFja2dyb3VuZCBzdGF0aW9uLCB3ZSBjYXJyeSBvdXQgdGhlIHNhbWUgYW5hbHlzaXMgZm9yIHRoZXNlIHN0YXRpb25zLgoKYGBge3J9CmRhdGEgJT4lIAogIGZpbHRlcihzaXRlX3R5cGUgPT0gImJhY2tncm91bmQiKSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSwgc2l0ZSkgJT4lIAogIHN1bW1hcmlzZShzaGFyZV9taXNzaW5nID0gc3VtKG1pc3NpbmcpL24oKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgY291bnQoc2hhcmVfbWlzc2luZykgJT4lIAogIG11dGF0ZSgKICAgIHByb3AgPSBuL3N1bShuKSwKICAgIHByb3BfaWZfbWlzc2luZyA9IGlmZWxzZShzaGFyZV9taXNzaW5nICE9IDAsIG4vKHN1bShuKSAtIG5bMV0pLCBOQSkKICApICU+JSAKICBrYWJsZShjb2wubmFtZXMgPSBjKCJTaGFyZSBvZiBwb2xsdXRhbnRzIG1lYXN1cmVkIGluIHRoZSBzdGF0aW9uIGZvciB3aGljaCBjb25jZW50cmF0aW9uIGRhdGEgaXMgbWlzc2luZyIsICJOdW1iZXIgb2YgZGF0ZXMiLCAiUHJvcG9ydGlvbiIsICJQcm9wb3J0aW9uIGFtb25nIGRhdGVzIHdpdGggbWlzc2luZyBvYnNlcnZhdGlvbnMiKSwgY2FwdGlvbiA9ICJPbmx5IGluIGJhY2tncm91bmQgc3RhdGlvbnMiKQpgYGAKCiMjIyBBY3Jvc3Mgc3RhdGlvbnMgaW4gYSBjaXR5CgpVbHRpbWF0ZWx5LCBhbmFseXNlcyBzdHVkeWluZyBoZWFsdGggZWZmZWN0cyBvZiBhaXIgcG9sbHV0aW9uIG9mdGVuIG9ubHkgdXNlIG9uZSBtZWFzdXJlIG9mIGNvbmNlbnRyYXRpb24gcGVyIGNpdHkgYW5kIHBlciBkYXRlLiBJbiBtb3N0IGNhc2VzLCB0aGVyZSBhcmUgc2V2ZXJhbCBhaXIgcG9sbHV0aW9uIG1lYXN1cmVtZW50IHN0YXRpb25zIHBlciBjaXR5LiBUbyBnZXQgYSB1bmlxdWUgbWVhc3VyZSBvZiBhaXIgcG9sbHV0aW9uIGZvciBhIGdpdmVuIGNpdHksIHRoZSBjb21tb24gcHJhY3RpY2UgY29uc2lzdHMgaW4gYXZlcmFnaW5nIHBvbGx1dGFudHMgY29uY2VudHJhdGlvbnMgZnJvbSBhbGwgYmFja2dyb3VuZCBzdGF0aW9ucyBpbiB0aGlzIGNpdHkuIFdlIG1heSB3b25kZXIgdG8gd2hhdCBleHRlbnQgY29uY2VudHJhdGlvbiBkYXRhIGlzIHNpbXVsdGFuZW91c2x5IG1pc3NpbmcgaW4gc2V2ZXJhbCBzdGF0aW9ucyBvZiBhIGdpdmVuIGNpdHkuIFdlIHRoZXJlZm9yZSBjb21wdXRlIHRoZSBhdmVyYWdlIHByb3BvcnRpb24gb2Ygc3RhdGlvbnMgcGVyIGNpdHkgaW4gd2hpY2ggZGF0YSBtaXNzaW5nLgoKYGBge3J9CmRhdGEgJT4lIAogIGZpbHRlcihzaXRlX3R5cGUgPT0gImJhY2tncm91bmQiKSAlPiUKICBncm91cF9ieShkYXRlLCBwb2xsdXRhbnQsIGNpdHkpICU+JSAKICBzdW1tYXJpc2Uoc2hhcmVfbWlzc2luZyA9IHN1bShtaXNzaW5nKS9uKCkpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGNvdW50KHNoYXJlX21pc3NpbmcpICU+JSAKICBtdXRhdGUoCiAgICBwcm9wID0gbi9zdW0obiksCiAgICBwcm9wX2lmX21pc3NpbmcgPSBpZmVsc2Uoc2hhcmVfbWlzc2luZyAhPSAwLCBuLyhzdW0obikgLSBuWzFdKSwgTkEpCiAgKSAlPiUgCiAga2FibGUoY29sLm5hbWVzID0gYygiU2hhcmUgb2Ygc3RhdGlvbnMgaW4gYSBjaXR5IGZvciB3aGljaCBjb25jZW50cmF0aW9uIGRhdGEgaXMgbWlzc2luZyIsICJOdW1iZXIgb2YgZGF0ZXMiLCAiUHJvcG9ydGlvbiIsICJQcm9wb3J0aW9uIGFtb25nIGRhdGVzIHdpdGggbWlzc2luZyBvYnNlcnZhdGlvbnMiKSwgY2FwdGlvbiA9ICJPbmx5IGluIGJhY2tncm91bmQgc3RhdGlvbnMiKQpgYGAKCgoKIyMgTGVuZ3RoIG9mIHBlcmlvZHMgd2l0aCBtaXNzaW5nIG9ic2VydmF0aW9ucwoKSW4gdGhpcyBzZWN0aW9uLCB3ZSBleHBsb3JlIHRoZSBsZW5ndGggb2YgcGVyaW9kcyB3aXRoIG1pc3Npbmcgb2JzZXJ2YXRpb25zLiBUaGlzIGxlbmd0aCBtYXkgcHJvdmlkZSBpbmZvcm1hdGlvbiBvbiBjYXVzZXMgb2YgbWlzc2luZ25lc3MuIE1pc3Npbmcgb2JzZXJ2YXRpb25zIGZvciBsb25nIHBlcmlvZHMgb2YgdGltZSBtYXkgYmUgaW5kaWNhdGl2ZSBvZiBjbHV0dGVyZWQgZmlsdGVycyBvZiBicm9rZW4gaW5zdHJ1bWVudC4gV2UgYWxzbyBleHBsb3JlIHdoZXRoZXIgdGhlIGxlbmd0aCBvZiBtaXNzaW5nbmVzcyBwYXR0ZXJucyBpcyBjb3JyZWxhdGVkIHdpdGggd2VhdGhlciB2YXJpYWJsZXMuCgpGaXJzdCwgd2UgZXhwbG9yZSB0aGUgbGVuZ3RoIG9mIG1pc3Npbmcgb2JzZXJ2YXRpb25zIGJ5IGxvb2tpbmcgYXQgdGhlIGRpc3BsYXlpbmcsIGluIGFuIGhlYXRtYXQsIGZvciBlYWNoIGNvdXBsZSBzdGF0aW9uKmRhdGUsIHdoZXRoZXIgY29uY2VudHJhdGlvbiBkYXRhIGlzIG1pc3NpbmcuIFdlIGJyZWFrIHRoaXMgZG93biBpbnRvIHllYXJzIGZvciByZWFkaWJpbGl0eS4gCgpgYGB7ciBoZWF0bWFwfQpoZWF0bWFwX21pc3NpbmduZXNzIDwtIGZ1bmN0aW9uKGRmLCB5KSB7CiAgCiAgZ3JhcGggPC0gZGYgJT4lIAogICAgZmlsdGVyKHllYXIgPT0geSkgJT4lIAogICAgZ3JvdXBfYnkoY2l0eSkgJT4lIAogICAgbXV0YXRlKHNpdGVfY2l0eSA9IHBhc3RlKGNpdHksIGFzLmludGVnZXIoZmFjdG9yKHNpdGUpKSwgc2VwID0gIl8iKSkgJT4lIAogICAgdW5ncm91cCgpICAlPiUKICAgIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSBzaXRlX2NpdHksIGZpbGwgPSBtaXNzaW5nKSkgKwogICAgZ2VvbV90aWxlKCkgKwogICAgIyB0aGVtZV9taW5pbWFsKCkgKwogICAgZmFjZXRfd3JhcCh+IHBvbGx1dGFudCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzU4MEUzQyIsICIjRkFCNzM3IikpICsKICAgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9IHBhc3RlKCJJbnRlcnZhbHMgd2l0aCBtaXNzaW5nIGNvbmNlbnRyYXRpb24gZGF0YSBwb2xsdXRhbnQgaW4iLCB5LCBzZXAgPSAiICIpLCB4ID0gIkRhdGUiLCB5ID0gICJBaXIgcG9sbHV0aW9uIHN0YXRpb24iKQogICAgCiAgcmV0dXJuKGdyYXBoKQp9CgpwdXJycjo6bWFwKGMoMjAxMywgMjAxNToyMDE5KSwgaGVhdG1hcF9taXNzaW5nbmVzcywgZGYgPSBkYXRhKQpgYGAKClRoZW4sIHdlIGxvb2sgYXQgdGhlIGxlbmd0aCBvZiBwZXJpb2RzIHdpdGggbWlzc2luZyBkYXRhLiBGaXJzdCwgd2UgY2FuIGVpdGhlciBjb3VudCBlYWNoIHRoZSBudW1iZXIgb2YgcGVyaW9kcyB3aXRoIGEgZ2l2ZW4gbGVuZ3RoICgqZWcqIDMgcGVyaW9kcyBoYXZlIGEgbGVuZ3RoIG9mIG1pc3NpbmcgZGF0YSBvZiA1IGhvdXJzKSBvciBjb3VudCB0aGUgbnVtYmVyIG9mIGRhdGVzIGJlbG9uZ2luZyB0byBwZXJpb2RzIHdpdGggYSBnaXZlbiBsZW5ndGggKGNvbnNpZGVyaW5nIHRoZSBzYW1lIGV4YW1wbGUsIDE1IGRhdGVzIGJlbG9uZyB0byBhIHBlcmlvZCBvZiBtaXNzaW5nIGRhdGEgb2YgbGVuZ3RoIDUgaG91cnMpLiBXZSBkZW5vdGUgdGhlIGZvcm1lciBjYXNlICJPbmUgb2JzZXJ2YXRpb24gcGVyIHBlcmlvZCIgYW5kIHRoZSBsYXRlciAiT25lIG9ic2VydmF0aW9uIHBlciBkYXRlIi4KCmBgYHtyfQojZ2l2ZSBlYWNoIG1pc3NpbmduZXNzIHBlcmlvZCBhbiBpZCAocm93X251bWJlciBvZiB0aGUgZmlyc3QgbWlzc2luZyBvYnNlcnZhdGlvbikKbGVuZ3RoX21pc3NpbmdfZGF0YSA8LSBkYXRhICU+JSAKICBtdXRhdGUocm93X2lkID0gcm93X251bWJlcigpKSAlPiUgCiAgZ3JvdXBfYnkoc2l0ZSwgcG9sbHV0YW50KSAlPiUKICBhcnJhbmdlKGRhdGUpICU+JSAKICBtdXRhdGUoCiAgICBtaXNzaW5nX3BlcmlvZF9pZCA9IGlmZWxzZShtaXNzaW5nID09IFRSVUUgJiBsYWcobWlzc2luZykgPT0gRkFMU0UsIHJvd19pZCwgTkEpCiAgKSAlPiUKICBmaWx0ZXIobWlzc2luZyA9PSBUUlVFKSAlPiUKICBmaWxsKG1pc3NpbmdfcGVyaW9kX2lkKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3QoLXJvd19pZCkgJT4lIAogIGFycmFuZ2UobWlzc2luZ19wZXJpb2RfaWQpICU+JSAKICBncm91cF9ieShtaXNzaW5nX3BlcmlvZF9pZCwgcG9sbHV0YW50KSAlPiUgCiAgbXV0YXRlKGxlbmd0aF9wZXJpb2RfbWlzc2luZyA9IG4oKSkgJT4lIAogIHVuZ3JvdXAoKQoKbGVuZ3RoX21pc3Npbmdfb25lX3Blcl9wZXJpb2QgPC0gbGVuZ3RoX21pc3NpbmdfZGF0YSAlPiUgCiAgY291bnQobWlzc2luZ19wZXJpb2RfaWQsIHBvbGx1dGFudCwgbmFtZSA9ICJsZW5ndGhfcGVyaW9kX21pc3NpbmciKQpgYGAKCiMjIyBEaXN0cmlidXRpb24gb2YgbGVuZ3RocyBvZiBtaXNzaW5nIGRhdGEKCmBgYHtyfQpncmFwaF9kaXN0cmliX2xlbmd0aCA8LSBmdW5jdGlvbihkZiwgZGVuc2l0eSwgYmluc19hZGp1c3QpIHsKICBncmFwaCA8LSBkZiAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBsZW5ndGhfcGVyaW9kX21pc3NpbmcpKSAKICAKICBpZiAoZGVuc2l0eSkgewogICAgZ3JhcGggPC0gZ3JhcGggKwogICAgICBnZW9tX2RlbnNpdHkoYWRqdXN0ID0gYmluc19hZGp1c3QsIGZpbGwgPSBtZWRpb2NyZXRoZW1lczo6Y29sb3JzX3RhYmxlJGJhc2VbMl0sIGFscGhhID0gMC42KQogIH0gZWxzZSB7CiAgICBncmFwaCA8LSBncmFwaCArCiAgICAgIGdlb21faGlzdG9ncmFtKGJpbnMgPSBiaW5zX2FkanVzdCkKICB9CiAgCiAgICBncmFwaCA8LSBncmFwaCArCiAgICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAnbG9nMTAnKSArCiAgICBmYWNldF93cmFwKH5wb2xsdXRhbnQpICsKICAgIGxhYnModGl0bGUgPSAiUmVwYXJ0aXRpb24gb2YgdGhlIGxlbmd0aCBvZiBwZXJpb2RzIG9mIG1pc3NpbmcgZGF0YSIsIHN1YnRpdGxlID0gIkNvbXBhcmlzb24gYWNyb3NzIHBvbGx1dGFudHMgLSBPbmUgb2JzZXJ2YXRpb24gcGVyIHBlcmlvZCIsIHggPSAiTnVtYmVyIG9mIGNvbnNlY3V0aXZlIGhvdXJzIG9mIG1pc3NpbmcgZGF0YSIpIAogICAgCiAgICByZXR1cm4oZ3JhcGgpCn0KCmdyYXBoX2Rpc3RyaWJfbGVuZ3RoKGxlbmd0aF9taXNzaW5nX29uZV9wZXJfcGVyaW9kLCBkZW5zaXR5ID0gRkFMU0UsIGJpbnNfYWRqdXN0ID0gMjApCgpncmFwaF9kaXN0cmliX2xlbmd0aChsZW5ndGhfbWlzc2luZ19vbmVfcGVyX3BlcmlvZCwgZGVuc2l0eSA9IFRSVUUsIGJpbnNfYWRqdXN0ID0gNCkKCmxlbmd0aF9taXNzaW5nX29uZV9wZXJfcGVyaW9kICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBsZW5ndGhfcGVyaW9kX21pc3NpbmcpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDIwKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gJ2xvZzEwJykgKwogIGZhY2V0X3dyYXAofnBvbGx1dGFudCkgKwogIAoKbGVuZ3RoX21pc3Npbmdfb25lX3Blcl9wZXJpb2QgJT4lIAogIGdncGxvdChhZXMoeCA9IGxlbmd0aF9wZXJpb2RfbWlzc2luZykpICsKICBnZW9tX2RlbnNpdHkoYWRqdXN0ID0gNCwgZmlsbCA9IG1lZGlvY3JldGhlbWVzOjpjb2xvcnNfdGFibGUkYmFzZVsyXSwgYWxwaGEgPSAwLjYpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAnbG9nMTAnKSArCiAgZmFjZXRfd3JhcCh+cG9sbHV0YW50KSArCiAgbGFicyh0aXRsZSA9ICJSZXBhcnRpdGlvbiBvZiB0aGUgbGVuZ3RoIG9mIHBlcmlvZHMgb2YgbWlzc2luZyBkYXRhIiwgc3VidGl0bGUgPSAiQ29tcGFyaXNvbiBhY3Jvc3MgcG9sbHV0YW50cyAtIE9uZSBvYnNlcnZhdGlvbiBwZXIgcGVyaW9kIiwgeCA9ICJOdW1iZXIgb2YgY29uc2VjdXRpdmUgaG91cnMgb2YgbWlzc2luZyBkYXRhIiwgeSA9ICJEZW5zaXR5IikgCmBgYAoKYGBge3J9Cmxlbmd0aF9taXNzaW5nX2RhdGEgJT4lIAogIGdncGxvdChhZXMoeCA9IGxlbmd0aF9wZXJpb2RfbWlzc2luZykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMjApICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAnbG9nMTAnKSArCiAgZmFjZXRfd3JhcCh+cG9sbHV0YW50KSArCiAgbGFicyh0aXRsZSA9ICJSZXBhcnRpdGlvbiBvZiB0aGUgbGVuZ3RoIG9mIHBlcmlvZHMgb2YgbWlzc2luZyBkYXRhIiwgc3VidGl0bGUgPSAiQ29tcGFyaXNvbiBhY3Jvc3MgcG9sbHV0YW50cyAtIE9uZSBvYnNlcnZhdGlvbiBwZXIgZGF0ZSIsIHggPSAiTnVtYmVyIG9mIGNvbnNlY3V0aXZlIGhvdXJzIG9mIG1pc3NpbmcgZGF0YSIsIHkgPSAgIkNvdW50IikgCgpsZW5ndGhfbWlzc2luZ19kYXRhICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBsZW5ndGhfcGVyaW9kX21pc3NpbmcpKSArCiAgZ2VvbV9kZW5zaXR5KGFkanVzdCA9IDIsIGZpbGwgPSBtZWRpb2NyZXRoZW1lczo6Y29sb3JzX3RhYmxlJGJhc2VbMl0sIGFscGhhID0gMC42KSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gJ2xvZzEwJykgKwogIGZhY2V0X3dyYXAofnBvbGx1dGFudCkgKwogIGxhYnModGl0bGUgPSAiUmVwYXJ0aXRpb24gb2YgdGhlIGxlbmd0aCBvZiBwZXJpb2RzIG9mIG1pc3NpbmcgZGF0YSIsIHN1YnRpdGxlID0gIkNvbXBhcmlzb24gYWNyb3NzIHBvbGx1dGFudHMgLSBPbmUgb2JzZXJ2YXRpb24gcGVyIGRhdGUiLCB4ID0gIk51bWJlciBvZiBjb25zZWN1dGl2ZSBob3VycyBvZiBtaXNzaW5nIGRhdGEiLCB5ID0gIkRlbnNpdHkiKSAKYGBgCgpgYGB7cn0KbGVuZ3RoX21pc3Npbmdfb25lX3Blcl9wZXJpb2QgJT4lIAogIG11dGF0ZShtaXNzaW5nX2xvbmdlcl9kYXkgPSBpZmVsc2UobGVuZ3RoX3BlcmlvZF9taXNzaW5nID4gMjQsIFRSVUUsIEZBTFNFKSkgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeCA9IG1pc3NpbmdfbG9uZ2VyX2RheSksIHN0YXQgPSAiY291bnQiKSArIAogIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIHBlcmlvZHMgd2l0aCBtaXNzaW5nIGRhdGEgbG9uZ2VyL3Nob3J0ZXIgdGhhbiBhIGRheSIsIHN1YnRpdGxlID0gIk9uZSBvYnNlcnZhdGlvbiBwZXIgcGVyaW9kIiwgeCA9ICJNaXNzaW5nIHBlcmlvZCBsb25nZXIgdGhhbiBhIGRheSIsIHkgPSAgIkNvdW50IikgCmBgYAoKYGBge3J9Cmxlbmd0aF9taXNzaW5nX2RhdGEgJT4lIAogIG11dGF0ZShtaXNzaW5nX2xvbmdlcl9kYXkgPSBpZmVsc2UobGVuZ3RoX3BlcmlvZF9taXNzaW5nID4gMjQsIFRSVUUsIEZBTFNFKSkgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeCA9IG1pc3NpbmdfbG9uZ2VyX2RheSksIHN0YXQgPSAiY291bnQiKSArIAogIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIHBlcmlvZHMgd2l0aCBtaXNzaW5nIGRhdGEgbG9uZ2VyL3Nob3J0ZXIgdGhhbiBhIGRheSIsIHN1YnRpdGxlID0gIk9uZSBvYnNlcnZhdGlvbiBwZXIgZGF0ZSIsIHggPSAiTWlzc2luZyBwZXJpb2QgbG9uZ2VyIHRoYW4gYSBkYXkiLCB5ID0gICJDb3VudCIpIApgYGAKCiMjIyBDb29yZWxhdGlvbiBiZXR3ZWVuIG1pc3NpbmduZXNzIGxlbmd0aCBhbmQgd2VhdGhlciB2YXJpYWJsZXMKCmBgYHtyfQpwbG90X2V2b2x1dGlvbl9sZW5ndGggPC0gZnVuY3Rpb24oZGYsIHZhciwgcGVyKSB7CiAgdmFyX25hbWUgPC0gc3RyX3JlcGxhY2VfYWxsKHZhciwgcGF0dGVybiA9ICJfIiwgcmVwbGFjZW1lbnQgPSAiICIpCiAgCiAgZ3JhcGggPC0gZGYgJT4lIAogICAgZ2dwbG90KCkgKyAKICAgIGdlb21fYmluMmQoYWVzKHggPSAuZGF0YVtbdmFyXV0sIHkgPSAuZGF0YVtbImxlbmd0aF9wZXJpb2RfbWlzc2luZyJdXSkpICsKICAgIHNjYWxlX3lfY29udGludW91cyh0cmFucyA9ICdsb2cxMCcpICsgCiAgICBsYWJzKHRpdGxlID0gcGFzdGUoIlJlbGF0aW9uc2hpcCBiZXR3ZWVuIGxlbmd0aCBvZiBwZXJpb2RzIHdpdGggbWlzc2luZyBkYXRhIiwgdmFyX25hbWUpLCBzdWJ0aXRsZSA9IHBhc3RlKCJPbmUgb2JzZXJ2YXRpb24gcGVyIiwgcGVyKSwgeCA9IHN0cl90b19zZW50ZW5jZSh2YXJfbmFtZSksIHkgPSAgIkxlbmd0aCBvZiBtaXNzaW5nIHBlcmlvZCAoaW4gaG91cnMpIikgCiAgCiAgaWYgKHN1YnN0cih2YXIsIDEsIDgpID09ICJ3aW5kX2RpciIpIHsKICAgIGdyYXBoIDwtIGdyYXBoICsKICAgICAgY29vcmRfcG9sYXIoKQogIH0KICAgIAogIHJldHVybihncmFwaCkKfQpgYGAKCgpgYGB7cn0KcHVycnI6Om1hcChjb3ZhcmlhdGVzX3dlYXRoZXIsIHBsb3RfZXZvbHV0aW9uX2xlbmd0aCwgZGYgPSBsZW5ndGhfbWlzc2luZ19kYXRhLCBwZXIgPSAiZGF0ZSIpCmBgYAoKSGVyZSB3ZSBjb25zaWRlciB0aGUgd2VhdGhlciB3aGVuIHZhcmlhYmxlcyBzdGFydGVkIG1pc3NpbmcuIEl0IG1ha2Ugc2Vuc2UgdG8gbG9vayBpbnRvIHRoaXMgYmVjYXVzZSBpZiBtaXNzaW5nbmVzcyBpcyBjYXVzZWQgYnkgc29tZSB3ZWF0aGVyIGZlYXR1cmUsIFRoZSB3ZWF0aGVyIGR1cmluZyB0aGUgZmlyc3QgbWlzc2luZyBvYnNlcnZhdGlvbiB3b3VsZCBiZSB0aGUgb25lIHRvIGxvb2sgaW50by4KCmBgYHtyfQp3ZWF0aGVyX2xlbmd0aF9kYXRhIDwtIGxlbmd0aF9taXNzaW5nX2RhdGEgJT4lIAogIGdyb3VwX2J5KG1pc3NpbmdfcGVyaW9kX2lkKSAlPiUgCiAgbXV0YXRlKG9ic2VydmF0aW9uX251bWJlciA9IHJvd19udW1iZXIoKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKG9ic2VydmF0aW9uX251bWJlciA9PSAxKSAKCnB1cnJyOjptYXAoY292YXJpYXRlc193ZWF0aGVyLCBwbG90X2V2b2x1dGlvbl9sZW5ndGgsIGRmID0gd2VhdGhlcl9sZW5ndGhfZGF0YSwgcGVyID0gInBlcmlvZCIpCmBgYAoKCgoKCg==